package com.aierkeji.call.cms.service;

import java.sql.Timestamp;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.DigestUtils;

import com.aierkeji.call.cms.contants.Contants;
import com.aierkeji.call.cms.dao.jpa.AkjCallUserDao;
import com.aierkeji.call.cms.entity.AkjCallRole;
import com.aierkeji.call.cms.entity.AkjCallUser;
import com.aierkeji.call.cms.shiro.MyUserNamePasswordToken;
import com.aierkeji.call.cms.util.AppConfig;
import com.aierkeji.call.cms.util.DateTimeUtils;
import com.aierkeji.call.cms.util.ResultCode;
import com.aierkeji.call.cms.util.ResultMapHelper;
import com.aierkeji.call.cms.util.StringUtils;

@Service
public class AkjCallLoginService {
	private final Logger log = LogManager.getLogger(getClass());
	@Autowired
	AkjCallUserDao akjCallUserDao;
	@Autowired
	AkjCallB2cService akjCallB2cService;

	public Map<String, Object> login(Map<String, Object> map) {
		// TODO Auto-generated method stub
		String tel = (String) map.get("tel");
		String pwd = (String) map.get("pwd");
		if (StringUtils.checkAnyNull(tel, pwd)) {
			return ResultMapHelper.nullParamsResult();
		}
		Map<String, Object> resultMap = loginByPassword(pwd,tel);
		if (ResultMapHelper.isSuccess(resultMap)) {
			
			
			return checkLoginSuccessAfter(resultMap);
		} else {
			if (!CollectionUtils.isEmpty(resultMap)) {
				return resultMap;
			}
		}
		return ResultMapHelper.failure("登陆失败！");
	}

	/**
	 * 检验登陆信息
	 * 
	 * @param pwd
	 * @param tel
	 * @return
	 */
	public Map<String, Object> loginByPassword(String pwd, String tel) {
		if (StringUtils.checkAnyNull(tel, pwd)) {
			return ResultMapHelper.nullParamsResult();
		}
		AkjCallUser callUser = akjCallUserDao.findByAccountAndIsDelete(tel, false);
		if (callUser == null) {
			return ResultMapHelper.failure("登陆失败，账号或者密码错误！");
		}
		if (callUser.getPwd().equals(DigestUtils.md5DigestAsHex(pwd.getBytes()))) {
			return ResultMapHelper.success(callUser);
		}
		return ResultMapHelper.failure("登陆失败，账号或者密码错误！");
	}
	public Map<String, Object> getYzm(Map<String, Object> map) {
		// TODO Auto-generated method stub
		String tel = (String) map.get("tel");
		String scene = (String) map.get("scene");
		if (StringUtils.checkAnyNull(tel, scene)) {
			return ResultMapHelper.nullParamsResult();
		}
		int count = akjCallUserDao.countByAccountAndIsDelete(tel, false);
		 String sessionId = SecurityUtils.getSubject().getSession().getId().toString();
		Date sendTime = (Date) SecurityUtils.getSubject().getSession().getAttribute(Contants.YZM_TIME + "_" + scene);
		if (count <= 0) {
			return ResultMapHelper.failure("找不到该用户！");
		}
		String sendTimeStr = DateTimeUtils.converDateToString(sendTime, "yyyy-MM-dd HH:mm:ss");
		map.put("sendTime", sendTimeStr);
		Map<String, Object> resultMap = akjCallB2cService.getYzm(map);
		if (ResultMapHelper.isSuccess(resultMap)) {
			Map<String, Object> data = (Map<String, Object>) resultMap.get("data");
			String yzm = (String) data.get("yzm");
			String yzmTimeStr = (String) data.get(Contants.YZM_TIME);
			Timestamp time = DateTimeUtils.converStrToTimestamp(yzmTimeStr);
			SecurityUtils.getSubject().getSession().setAttribute(Contants.YZM_KEY + "_" + scene, yzm);
			SecurityUtils.getSubject().getSession().setAttribute(Contants.YZM_TIME + "_" + scene, time);
			SecurityUtils.getSubject().getSession().setAttribute(Contants.YZM_TEL + "_" + scene, tel);
			SecurityUtils.getSubject().getSession().setAttribute(Contants.YZM_CHECK_COUNT + "_" + scene, 0);
			Map<String,Object> resultMapData = (Map<String,Object>)resultMap.get("data");
			if(resultMapData==null) {
				resultMapData = new HashMap<String, Object>();
			}
			resultMapData.put("token", sessionId);
			if (!"dev".equals(AppConfig.getProperty("env"))) {
				resultMapData =  new HashMap<String, Object>();
				resultMapData.put("token", sessionId);
				return ResultMapHelper.success(resultMapData);
			}
			
		} else {
			if (!CollectionUtils.isEmpty(resultMap)) {
				return resultMap;
			}else {
				return ResultMapHelper.failure("发送短信失败！");
			}
		}
		
		return resultMap;
	}

	public Map<String, Object> loginByYzm(Map<String, Object> map) {
		// TODO Auto-generated method stub
		String tel = (String) map.get("tel");
		String yzm = (String) map.get("yzm");
		if (StringUtils.checkAnyNull(tel, yzm)) {
			return ResultMapHelper.nullParamsResult();
		}
		Session session = SecurityUtils.getSubject().getSession();
		Date sendTime = (Date) session.getAttribute(Contants.YZM_TIME + "_" + Contants.YZM_LOGIN);
		String sessionYzm = (String) session.getAttribute(Contants.YZM_KEY + "_" + Contants.YZM_LOGIN);
		String sessionTel = (String) session.getAttribute(Contants.YZM_TEL + "_" + Contants.YZM_LOGIN);
		Integer checkCount = (Integer) session.getAttribute(Contants.YZM_CHECK_COUNT + "_" + Contants.YZM_LOGIN);
		map.put("sessionYZM", sessionYzm);
		map.put("sendTime",DateTimeUtils.converDateToString(sendTime,DateTimeUtils.DATE_PATTERN_TIMESTAMP));
		map.put("sessionTel", sessionTel);
		map.put("checkCount", checkCount);
		Map<String, Object> resultMap = this.akjCallB2cService.logingByYzm(map);
		if (ResultMapHelper.isSuccess(resultMap)) {
			removeYZM(Contants.YZM_LOGIN);
			AkjCallUser callUser = akjCallUserDao.findByAccountAndIsDelete(tel, false);
			if (callUser == null) {
				return ResultMapHelper.failure("登陆失败，账号或者密码错误！");
			}
			resultMap.put("data", callUser);
			
			return checkLoginSuccessAfter(resultMap);
		} else {
			if (!CollectionUtils.isEmpty(resultMap)) {
				String status = (String)resultMap.get("status");
				if(ResultCode.CODE_ERROR_106.equals(status)) {// 验证码失败次数超过5次
					removeYZM(Contants.YZM_LOGIN);
				}
				session.setAttribute(Contants.YZM_CHECK_COUNT + "_" + Contants.YZM_LOGIN, ++checkCount);
				
				return resultMap;
			}
		}
		return ResultMapHelper.failure("验证失败！");
	}

	private Map<String, Object> checkLoginSuccessAfter(Map<String, Object> checkResult) {
		AkjCallUser callUser = (AkjCallUser) checkResult.get("data");
		UsernamePasswordToken token = new MyUserNamePasswordToken(callUser, callUser.getPwd());
		Subject subject = SecurityUtils.getSubject();
		try {
			subject.login(token);
			subject.getSession().setAttribute("loginUser", callUser);
			SecurityUtils.getSubject().getSession()
					.setTimeout(Long.parseLong(AppConfig.getProperty("sessionTimout", Contants.sessionTimeount + "")));
			subject.isPermitted("666");
			List<AkjCallRole> roles = callUser.getRoles();
			if (!CollectionUtils.isEmpty(roles)) {
				callUser.setRolesCode(roles.stream().map(k -> k.getCode()).collect(Collectors.toSet()));
			}
			callUser.setToken(SecurityUtils.getSubject().getSession().getId().toString());
			AkjCallUser akjCallUser = new AkjCallUser();
			BeanUtils.copyProperties(callUser, akjCallUser);
			akjCallUser.setPwd(null);
 			return ResultMapHelper.success(akjCallUser);
		} catch (UnknownAccountException uae) {
			return ResultMapHelper.result(ResultCode.CODE_ERROR_101, "账户不存在");
		} catch (IncorrectCredentialsException ice) {
			return ResultMapHelper.result(ResultCode.CODE_ERROR_102, "密码错误");
		}
	}
	
	private void removeYZM(String sence) {
		SecurityUtils.getSubject().getSession().removeAttribute(Contants.YZM_TIME + "_" + sence);
		SecurityUtils.getSubject().getSession().removeAttribute(Contants.YZM_KEY + "_" +sence);
		SecurityUtils.getSubject().getSession().removeAttribute(Contants.YZM_TEL + "_" + sence);
		SecurityUtils.getSubject().getSession().removeAttribute(Contants.YZM_CHECK_COUNT + "_" + sence);
	}

}
